//
// Created by Snow on 2023/3/20.
//
#include<cstdio>
#define MaxSize 50
typedef struct
{
    char data[MaxSize];//存放串字符
    int length;//存放串长
}SqString;//顺序串类型
//生成串
void StrAssign(SqString &s,char cstr[])
{
    int i;
    for(i=0;cstr[i]!='\0';i++)
        s.data[i]=cstr[i];
    s.length=i;
}
void DispStr(SqString s)
{
    int i;
    if(s.length>0)
    {
        for(i=0;i<s.length;i++)
            printf("%c",s.data[i]);
        printf("\n");
    }
}
//BF算法（暴力算法）
int BF(SqString s,SqString t)
{
    int i=0,j=0;
    while(i<s.length&&j<t.length)//两个串都没有扫描完时循环
    {
        if(s.data[i]==t.data[j])//当前比较的两个字符相同
        {
            i++;
            j++;//依次比较后续的两个字符
        }
        else//当前比较的两个字符不相同
        {
            i=i-j+1;
            j=0;//扫描目标串的i的回退，子串从头开始匹配
        }
    }
    if(j>=t.length)//j超界，表示t是s的子串
        return(i-t.length);//返回t在s中的位置
    else//模式匹配失败
        return(-1);//返回-1
}
//KMP算法
void GetNext(SqString t,int next[])//由模式串t求出next数组
{
    int j,k;
    j=0;
    k=-1;//j扫描t，k记录t[j]之前与t开头相同的字符个数
    next[0]=-1;//设置next[0]值
    while(j<t.length-1)//求t所有位置的next值
    {
        if(k==-1||t.data[j]==t.data[k])//k为-1或比较的字符串相等时
        {
            j++;
            k++;//j、k一次移动到下一个字符
            next[j]=k;//设置next[j]为k
        }
        else
            k=next[k];//k回退
    }
}
int KMPIndex(SqString s,SqString t)//KMP算法
{
    int next[MaxSize],i=0,j=0;
    GetNext(t,next);
    while(i<s.length&&j<t.length)
    {
        if(j==-1||s.data[i]==t.data[j])
        {
            i++;
            j++;//i、j各增1
        }
        else
            j=next[j];//i不变，j后退
    }
    if(j>=t.length)
        return(i-t.length);
    else
        return(-1);
}
//改进KMP算法
void GetNextval(SqString t,int nextval[])
{
    int j=0,k=-1;
    nextval[0]=-1;
    while(j<t.length)
    {
        if(k==-1||t.data[j]==t.data[k])
        {
            j++;
            k++;
            if(t.data[j]!=t.data[k])
            {
                nextval[j]=k;
            }
            else
                nextval[j]=nextval[k];
        }
        else
            k=nextval[k];
    }
}
int KMPIndex1(SqString s,SqString t)//改进后的KMP算法
{
    int nextval[MaxSize],i=0,j=0;
    GetNextval(t,nextval);
    while(i<s.length&&j<t.length)
    {
        if(j==-1||s.data[i]==t.data[j])
        {
            j++;
            i++;
        }
        else
            j=nextval[j];
    }
    if(j>=t.length)
        return(i-t.length);
    else
        return(-1);
}
int main()
{
    char str[]="aaaaab",arr[]="aaab";
    SqString s,t;
    StrAssign(s,str);
    StrAssign(t,arr);
    DispStr(s);
    DispStr(t);
    printf("BF:%d\n",BF(s,t));
    printf("KMP:%d\n",KMPIndex(s,t));
    printf("KMP Up:%d\n", KMPIndex1(s,t));
}